package com.ztr.designpatterns.singleton;

/**为了确保线程安全，加了synchronized锁*/
//懒汉单例模式
public class LazySingleton{
    private static LazySingleton instance = null;
    private LazySingleton(){}

    /**此模式虽然安全，但是由于把锁加到方法上后，所有的访问都会因为需要锁占用导致资源的浪费，如果不是特殊情况不建议使用此种单例模式*/
//    //使用synchronized关键字对方法加锁，确保任意时刻只有一个线程可执行该方法
//    public static synchronized LazySingleton getInstance(){
//        if(instance==null){
//            instance = new LazySingleton();
//        }
//        return instance;
//    }


//    public static LazySingleton getInstance() {
//        if (instance == null) {
//            synchronized (LazySingleton.class) {
//                instance = new LazySingleton();
//            }
//        }
//        return instance;
//    }

    /**
     * 使用双重检查锁定来实现懒汉式单例模式。
     * volatile修饰的成员变量可以确保多个线程能够正确处理，但是volatile关键字会屏蔽Java虚拟机所做的一切代码优化，所以可能会导致系统的运行效率降低。
     * 上面存在的问题：单例对象不唯一的情况。
     * 例如在某一瞬间，线程A和线程B都在调用getInstance()方法，此时instance对象为null值，均能通过instance==null的判断。
     * 由于实现了synchronized加锁机制，线程A执行完毕后进入synchronized锁定的代码中执行实例创建代码。
     * 但是当A执行完毕时线程B并不知道实例已经创建，将继续创建新的实例，导致产生多个实例，违背了单例模式的设计思想，因此需要进一步改进，
     * 在synchronized中再进行一次instance==null的判断，称为双重检查锁定。
     * @return instance
     */
    public static LazySingleton getInstance() {
        //第一重判断
        if (instance == null) {
            //锁定代码块
            synchronized (LazySingleton.class) {
                //第二重判断
                if (instance == null) {
                    instance = new LazySingleton();//创建单例实类
                }
            }
        }
        return instance;
    }

}
